#ifndef __CGSHADERPROGRAM_H__
#define __CGSHADERPROGRAM_H__

#include "ShaderProgram.h"
#include "Cg/cg.h"

namespace RayFrame
{
  class CGEffect;
  class CGShader;

  /** Shader program clas for nvidia cg.
  Both vertex and pixel shader are called "shader program"
  in cg's document. However CGShaderProgram in RayFrame
  is composed of both pixel and vertex shader. And we don't
  call vertex program or pixel program.
  **/
  class CGShaderProgram: public ShaderProgram
  {
  protected:
    CGShader *m_cgVs, *m_cgPs;

    typedef std::map<STRING, CGparameter> ShaderVarMap;
    typedef ShaderVarMap::iterator ShaderVarMapIter;
    typedef std::vector<CGparameter> ShaderTexVec;
    typedef ShaderTexVec::iterator ShaderTexVecIter;

    ShaderVarMap m_handles[2];  ///< veriables parameters for shaders
    ShaderTexVec m_cgTextures;
  protected:
    virtual void internalCreate();
    virtual void internalDestroy();
  public:
    virtual void Begin();
    virtual void End();
    virtual bool BindImage(STRING varName, Texture* image, Shader::ShaderType type);
  public:
    CGShaderProgram();
    ~CGShaderProgram(){ internalDestroy(); };

    virtual Shader* CreateVertexShader();
    virtual Shader* CreatePixelShader();

    CGparameter GetHandle(Shader::ShaderType type, STRING name);

    /// return True if no error
    static bool CheckError();;

    virtual void SetShaderParam(STRING name, const int val, Shader::ShaderType type = Shader::VERTEX_SHADER);
    virtual void SetShaderParam(STRING name, const float val, Shader::ShaderType type = Shader::VERTEX_SHADER);
    virtual void SetShaderParam(STRING name, glm::vec2 val, Shader::ShaderType type = Shader::VERTEX_SHADER);
    virtual void SetShaderParam(STRING name, glm::vec3 val, Shader::ShaderType type = Shader::VERTEX_SHADER);
    virtual void SetShaderParam(STRING name, glm::vec4 val, Shader::ShaderType type = Shader::VERTEX_SHADER);
    virtual void SetShaderParam(STRING name, glm::mat4 val, Shader::ShaderType type = Shader::VERTEX_SHADER);
  };
}

#endif